package hu.vissy.yacap.option;

import hu.vissy.yacap.exception.CommandLineParserException;

/**
 * Enumerated value option.
 *
 *
 * @author balage
 *
 * @param <T>
 *            Type of the enum class.
 */
public class EnumOption<T extends Enum<?>> extends CommandLineOption<T> {


    /**
     * The associated enum type.
     */
//    private Class<? extends Enum<?>> enumClass;

    public static class Builder<E extends Enum<?>> extends CommandLineOptionBuilder<E, Builder<E>> {
        private Class<? extends Enum<?>> enumClass;

        public Builder(String longForm, Class<? extends Enum<?>> clazz) {
            super(clazz, longForm);
            enumClass = clazz;
            setValueList();
        }

        /**
         * Uses covariant return type to precast result.
         */
        @Override
        public EnumOption<E> getInstance() {
            return (EnumOption<E>) super.getInstance();
        }

        @Override
        protected CommandLineOption<E> createInstance() {
            return new EnumOption<E>(longForm, enumClass);
        }


        @Override
        protected Builder<E> getThis() {
            return this;
        }

        public Builder<E> useLowerCaseValueList() {
            valueName = valueName.toLowerCase();
            return getThis();
        }

        /**
         * @return the enumClass
         */
        public Class<? extends Enum<?>> getEnumClass() {
            return enumClass;
        }

        /*
         * Setting value name as the list of the possible values extracted from
         * the associated enumeration class.
         */
        private final void setValueList() {
            String s = "";
            for (Object ev : enumClass.getEnumConstants()) {
                s += " | " + ev;
            }
            if (s.length() > 0) {
                s = s.substring(3);
            }
            valueName = s;
        }


    }


    /**
     * Constructor.
     *
     * @param longForm
     *            The long name of the command.
     * @param clazz
     *            The enumeration class to associated the parameter with.
     */
    public EnumOption(String longForm, Class<? extends Enum<?>> clazz) {
        super(clazz, longForm);
    }

    @SuppressWarnings("unchecked")
    @Override
    public T parseValue(String valueString) throws CommandLineParserException {
        for (Enum<?> s : ((Class<? extends Enum<?>>) getDataType()).getEnumConstants()) {
            if (s.name().equals(valueString.toUpperCase())) {
                return (T) s;
            }
        }
        throw new CommandLineParserException("Unknown enum value " + valueString + " for enum " + getDataType().getCanonicalName());
    }

}
